#include <iostream>
#include "netselect.h"
#include "bufstream.h"
#include "netpacket.h"
#include "Build/msgLoginServer.h"

using namespace std;
void ProcessPacket( CNetSelect &net, xgc_byte type, xgc_byte code, bufstream& packet );
void ProcessSystem( CNetSelect &net, xgc_byte type, xgc_byte code, bufstream& packet );
void ProcessLoginServer( CNetSelect &net, xgc_byte type, xgc_byte code, bufstream& s );

int main(int argc, char* argv[])
{
	if( argc < 2 )
	{
		cout << "type : example ip port" << endl;
		return -1;
	}
	
	// declare network
    CNetSelect net;

	cout << "connect server" << argv[1] << ":" << 6666 << endl;

	// connect server using address and port
    net.Connect( argv[1], 6666);

	// declare packet
	CNetPacket<4096> mPacket(net);

	// first declare a message
	msgLoginRequest login;

	// put request field into
	login.username = "albert";
	login.password = "123456";

	// send this message
	xgc_int32 send_bytes = 0;
	try
	{
		send_bytes = mPacket.Send< 4096 >( login );
	}
	catch ( std::logic_error& e )
	{
		std::cout << "error send bytes " << send_bytes << endl;
		net.Disconnect();
		return -1;
	}

	// judge send was complated.
	if( send_bytes < 0 )
	{
		std::cout << "error send bytes " << send_bytes << endl;
		net.Disconnect();
		return -1;
	}



    while(1)
    {
		try
		{
			// reveive network packet
			xgc_lpcstr packet =  mPacket.Done();

			// judge packet has received complated.
			if( packet )
			{
				// dispatch message to process function.
				xgc_uint16 length = *(xgc_uint16*)packet;

				bufstream s( packet, length );

				xgc_byte type, code;
				s >> length >> type >> code;
				
				ProcessPacket( net, type, code, s );

				// must mark this packet was finished.
				mPacket.Next();
			}
		}
		catch( std::logic_error& error )
		{
			cout << error.what() << endl;
		}
	}
    return 0;
}

void ProcessPacket( CNetSelect &net, xgc_byte type, xgc_byte code, bufstream& s )
{
	switch( type )
	{
		case 0:
			ProcessSystem( net, type, code, s );
			break;
		case LS2C_LOGIN_MESSAGE_TYPE:
			ProcessLoginServer( net, type, code, s );
			break;
	}
}	

void ProcessSystem( CNetSelect &net, xgc_byte type, xgc_byte code, bufstream& s )
{
	xgc_byte buffer[256];
	switch( code )
	{
		case 4: // PING MESSAGE
			{
				xgc_uint32 c;
				s >> c;
	
				bufstream buf( buffer, 256 );
				buf << xgc_uint16(8) << xgc_byte(0) << xgc_byte(5) << c;

				net.Send( (xgc_lpcstr)buf.base(), buf.wd() );
			}
			break;				
	}
}

void ProcessLoginServer( CNetSelect &net, xgc_byte type, xgc_byte code, bufstream& s )
{
	switch( code )
	{
		case LS2C_LOGIN_RESPONSE:
			msgLoginResponse rpn;
		    s >> rpn;

			cout << rpn.result << endl;
			break;
	}
}

